package com.qd.pay.thread;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qd.pay.domain.OrderReportNotifyDTO;
import com.qd.pay.model.OrderReportNotify;
import com.qd.pay.service.OrderReportNotifyService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author sjk
 */
@Slf4j
public class OrderNotifyThread extends Thread {

    private static final Long TIME_OUT = 5 * 60 * 1000L;
    private static final int PAGE_SIZE = 100;
    private static final Object locked = new Object();
    private final QueryWrapper<OrderReportNotify> queryWrapper;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private OrderReportNotifyService orderReportNotifyService;
    @Resource
    private OrderNotifyService orderNotifyService;
    private boolean done;

    public OrderNotifyThread() {
        queryWrapper = new QueryWrapper<>();
        queryWrapper.last("limit " + PAGE_SIZE);
        queryWrapper.orderByAsc("add_time");
    }

    @Override
    @Transactional(readOnly = true)
    public void run() {
        log.info("OrderNotifyThread启动");
        int errCode = 0;
        while (!done) {
            try {
                if (log.isDebugEnabled()) {
                    log.debug("OrderNotifyThread");
                }
                page(1);
                synchronized (this) {
                    wait(TIME_OUT);
                }
            } catch (InterruptedException e) {
                log.error("OrderNotifyThread,wait异常", e);
                Thread.currentThread().interrupt();
            } catch (Exception e) {
                errCode++;
                if (errCode == 10) {
                    log.error("OrderNotifyThread Exception", e);
                    errCode = 0;
                }
            }
        }
    }

    public void doDone() {
        done = true;
        queryWrapper.clear();
    }

    public void awaken() {
        synchronized (this) {
            notifyAll();
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void page(int idx) {
        final List<OrderReportNotify> list = orderReportNotifyService.getList(queryWrapper);
        log.info("OrderNotifyThread,待处理数据: {}", list.size());
        if (list.isEmpty()) {
            if (idx == 1) {
                page(++idx);
            }
        } else {
            final List<OrderReportNotifyDTO> rList = new ArrayList<>(PAGE_SIZE);
            for (OrderReportNotify orderReportNotify : list) {
                String key = "nid_" + orderReportNotify.getNid();
                synchronized (locked) {
                    String value = stringRedisTemplate.opsForValue().get(key);
                    if (StringUtils.hasLength(value)) {
                        log.info("OrderNotifyThread,已经处理,当前直接跳过,key: {}", key);
                        continue;
                    }
                    stringRedisTemplate.opsForValue().set(key, "a", 1, TimeUnit.HOURS);
                }
                final OrderReportNotifyDTO orderReportNotifyDto = orderReportNotifyService.modelToDto(orderReportNotify);
                rList.add(orderReportNotifyDto);
                orderReportNotify.freeData();
            }
            if (!rList.isEmpty()) {
                orderNotifyService.notifyAndSave(rList);
                rList.clear();
            }
            list.clear();
            page(++idx);
        }
    }

    public void removeSet(String nid) {
        String key = "nid_" + nid;
        synchronized (locked) {
            stringRedisTemplate.delete(key);
        }
    }
}
